package dom.xpath.query.xpath.expr;

import static dom.xpath.query.xpath.XPText.OPTCALC;
import dom.xpath.query.EvalException;
import dom.xpath.query.xpath.XPContext;
import dom.xpath.query.xpath.values.Calc;
import dom.xpath.query.xpath.values.Num;
import dom.xpath.query.xpath.values.Item;

/**
 * Calculation Expression.
 * 
 * @author Workgroup DBIS, University of Konstanz 2005-07, ISC License
 * @author Christian Gruen
 */
public final class Calculation extends DualExpr {
  /** Expression Type. */
  public Calc type;

  /**
   * Constructor.
   * @param e1 first expression (factor or dividend)
   * @param e2 second expression (factor or divisor)
   * @param t MultiplicativeExpr.MULTIPLICATION / DIVISION / MODULO
   */
  public Calculation(final Expression e1, final Expression e2, final Calc t) {
    expr1 = e1;
    expr2 = e2;
    type = t;
  }

  @Override
  public Num eval(final XPContext ctx) throws EvalException {
    return new Num(type.eval(ctx.eval(expr1).num(), ctx.eval(expr2).num()));
  }

  @Override
  public Expression compile(final XPContext ctx) throws EvalException {
    expr1 = expr1.compile(ctx);
    expr2 = expr2.compile(ctx);
    if(expr1 instanceof Item && expr2 instanceof Item) {
      ctx.compInfo(OPTCALC);
      final double d1 = ((Item) expr1).num();
      final double d2 = ((Item) expr2).num();
      return new Num(type.eval(d1, d2));
    }
    return this;
  }

  @Override
  public String toString() {
    return expr1 + " " + type + " " + expr2;
  }
}
